﻿using System;
using System.Collections.Generic;
using System.Transactions;
using Aocsoft.Infrastructure.DomainBase;
using Aocsoft.Infrastructure.RepositoryFramework;

namespace Aocsoft.Infrastructure
{
    public class UnitOfWork : IUnitOfWork
    {
        public Guid Key { get; private set; }
        public DateTime CreateDatetime { get; private set; }

        protected Dictionary<IEntity, IUnitOfWorkRepository> addedEntities;
        protected Dictionary<IEntity, IUnitOfWorkRepository> changedEntities;
        protected Dictionary<IEntity, IUnitOfWorkRepository> deletedEntities;



        public UnitOfWork()
        {
            Key = Guid.NewGuid();

            CreateDatetime = DateTime.UtcNow;

            this.addedEntities = new Dictionary<IEntity,
                                     IUnitOfWorkRepository>();
            this.changedEntities = new Dictionary<IEntity,
                                       IUnitOfWorkRepository>();
            this.deletedEntities = new Dictionary<IEntity,
                                       IUnitOfWorkRepository>();
        }

        #region IUnitOfWork Members

        public void RegisterAdded(IEntity entity,
            IUnitOfWorkRepository repository)
        {
            this.addedEntities.Add(entity, repository);
        }

        public void RegisterChanged(IEntity entity,
            IUnitOfWorkRepository repository)
        {
            this.changedEntities.Add(entity, repository);
        }

        public void RegisterRemoved(IEntity entity,
            IUnitOfWorkRepository repository)
        {
            this.deletedEntities.Add(entity, repository);
        }

        public virtual void Commit()
        {
            TransactionScope scope = new TransactionScope();
            try
            {
                foreach (IEntity entity in this.addedEntities.Keys)
                {
                    this.addedEntities[entity].PersistNewItem(entity);
                }

                foreach (IEntity entity in this.changedEntities.Keys)
                {
                    this.changedEntities[entity].PersistUpdatedItem(entity);
                }
                foreach (IEntity entity in this.deletedEntities.Keys)
                {
                    this.deletedEntities[entity].PersistDeletedItem(entity);
                }

                scope.Complete();
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                scope.Dispose();
                this.deletedEntities.Clear();
                this.addedEntities.Clear();
                this.changedEntities.Clear();
            }
        }
        #endregion
    }
}
